package com._9xcloud.leaverequest.service;

import com._9xcloud.leaverequest.domain.*;
import com._9xcloud.leaverequest.exception.ClientLogicalErrorException;
import com._9xcloud.leaverequest.exception.NotFoundException;
import com._9xcloud.leaverequest.repository.LeaveRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2015/5/28.
 */
@Repository
@Transactional
public class LeaveRequestServiceImpl implements LeaveRequestService {
    @Autowired
    private StudentService studentService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private LessonService lessonService;
    @Autowired
    private LeaveRequestRepository leaveRequestRepository;

    public LeaveRequest create(int studentId, int lessonId, String reason) {
        Student student = studentService.getById(studentId);
        Lesson lesson = lessonService.getById(lessonId);
        if (!student.getCourses().contains(lesson.getCourse())) {
            throw new ClientLogicalErrorException("You have no right to request leave for the lesson");
        }
        LeaveRequest leaveRequest = new LeaveRequest(student, lesson, reason);
        return leaveRequestRepository.saveAndFlush(leaveRequest);
    }

    @Transactional(readOnly = true)
    public LeaveRequest getById(int leaveRequestId) {
        LeaveRequest leaveRequest = leaveRequestRepository.findOne(leaveRequestId);
        if (leaveRequest == null) {
            throw new NotFoundException("Could not find the leave request");
        }
        return leaveRequest;
    }

    public LeaveRequest audit(int teacherId, int leaveRequestId, boolean isAgreed, String comment) {
        Teacher teacher = teacherService.getById(teacherId);
        LeaveRequest leaveRequest = getById(leaveRequestId);
        Student student = leaveRequest.getStudent();
        switch (leaveRequest.getStatus()) {
            case REQUEST_STATUS_WAITING_CLASS:
                if (!student.isOwnedByTeacher(teacher)) {
                    throw new ClientLogicalErrorException("You have no right to audit the leave request");
                }
                if (isAgreed)
                    leaveRequest.setStatus(LeaveRequestStatus.REQUEST_STATUS_WAITING_COLLEGE);
                else
                    leaveRequest.setStatus(LeaveRequestStatus.REQUEST_STATUS_REFUSED);
                leaveRequest.setTeacherComment(comment);
                break;
            case REQUEST_STATUS_WAITING_COLLEGE:
                if (teacher.getLevel() != TeacherLevel.T1 || !student.isOwnedByCollege(teacher.getCollege())) {
                    throw new ClientLogicalErrorException("You have no right to audit the leave request");
                }
                if (isAgreed)
                    leaveRequest.setStatus(LeaveRequestStatus.REQUEST_STATUS_AGREED);
                else
                    leaveRequest.setStatus(LeaveRequestStatus.REQUEST_STATUS_REFUSED);
                leaveRequest.setCollegeComment(comment);
                break;
            default:
                throw new ClientLogicalErrorException("You can't audit the leave request, because it's not under waiting audit.");
        }

        return leaveRequestRepository.saveAndFlush(leaveRequest);
    }

    public void removeAll() {
        leaveRequestRepository.deleteAll();
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByStudentId(int studentId) {
        return leaveRequestRepository.findByStudentId(studentId);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByStudentId(int studentId, LeaveRequestStatus status) {
        return leaveRequestRepository.findByStudentIdAndStatus(studentId, status);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByLessonId(int lessonId) {
        return leaveRequestRepository.findByLessonId(lessonId);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByLessonId(int lessonId, LeaveRequestStatus status) {
        return leaveRequestRepository.findByLessonIdAndStatus(lessonId, status);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByClazzId(int clazzId) {
        return leaveRequestRepository.findByClazzId(clazzId);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByClazzId(int clazzId, LeaveRequestStatus status) {
        return leaveRequestRepository.findByClazzId(clazzId, status);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByCollegeId(int collegeId) {
        return leaveRequestRepository.findByCollegeId(collegeId);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByCollegeId(int collegeId, LeaveRequestStatus status) {
        return leaveRequestRepository.findByCollegeId(collegeId, status);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByCourseId(int courseId) {
        return leaveRequestRepository.findByCourseId(courseId);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByCourseId(int courseId, LeaveRequestStatus status) {
        return leaveRequestRepository.findByCourseId(courseId, status);
    }

    @Transactional(readOnly = true)
    public List<LeaveRequest> getByTeacherId(int teacherId) {
        List<LeaveRequest> requests = new ArrayList<LeaveRequest>();
        Teacher teacher = teacherService.getById(teacherId);
        for (Clazz clazz : teacher.getClazzs()) {
            requests.addAll(leaveRequestRepository.findByClazzId(clazz.getId(), LeaveRequestStatus.REQUEST_STATUS_WAITING_CLASS));
        }
        if (teacher.getLevel() == TeacherLevel.T1) {
            requests.addAll(leaveRequestRepository.findByCollegeId(teacher.getCollege().getId(), LeaveRequestStatus.REQUEST_STATUS_WAITING_COLLEGE));
        }
        return requests;
    }
}
